﻿namespace MSSQL.Interface
{
	using CommandTool;
    using ComTools.Encrypt;
    using System;
	using System.Collections.Generic;
	using System.Data;
	using System.Data.SqlClient;

	/// <summary>
	/// 该类对接口进行了默认的实现，并定义了实际实现的抽象方法
	/// </summary>
	public abstract class AbstractDataExcute : IDataExcute
	{
		/// <summary>
		/// 设置该查询用例使用的库
		/// </summary>
		public string DataBaseName
		{
			set
			{
				try
				{
                    DatabaseInstance instance = DatabaseManager.GetDatabase(value);
                    connectionString = bool.Parse(instance.IsEncryption) ? AESEncryptHelper.Decrypt(instance.ConnectionString): instance.ConnectionString;
				}
				catch (Exception ex)
				{

					throw ex;
				}
			}
		}

		/// <summary>
		/// 链接字符串，从工具中读取配置
		/// </summary>
		private string connectionString = string.Empty;

		/// <summary>
		/// 获取连接
		/// </summary>
		/// <returns>打开的链接，如果失败返回的是null</returns>
		private IDbConnection GetConnection()
		{
			try
			{
				if (string.IsNullOrEmpty(connectionString)) return null;

				IDbConnection connection = new SqlConnection(connectionString);

				connection.Open();

				return connection;
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}

		/// <summary>
		/// 关闭连接
		/// </summary>
		/// <param name="conection">要关闭的链接</param>
		private void CloseConnection(IDbConnection connection)
		{
			try
			{
				if (connection != null && connection.State == ConnectionState.Open)
				{
					connection.Close();
					connection.Dispose();

				}
			}
			catch (Exception)
			{

				throw new Exception("关闭数据库连接时出错");
			}
		}

		/// <summary>
		/// 插入单条数据
		/// </summary>
		/// <typeparam name="T">插入的对象类型</typeparam>
		/// <param name="t">要插入的对象</param>
		/// <returns>插入结果</returns>
		public int InsertSingle<T>(T t)
		{
			IDbConnection connection = null;

			try
			{
				connection = GetConnection();
				if (connection == null) throw new ApplicationException("获取数据库连接失败");
				return InsertSingleDataImpl<T>(connection, t);
			}
			catch (Exception ex)
			{
				CloseConnection(connection);
				throw new Exception("插入单条数据出错"+ ex.ToString());
			}
			finally
			{
				CloseConnection(connection);
			}
		}

		/// <summary>
		/// 插入多条数据
		/// </summary>
		/// <typeparam name="T">插入的对象类型</typeparam>
		/// <param name="t">要插入的对象</param>
		/// <returns>插入结果</returns>
		public int InsertMultiple<T>(IList<T> t)
		{
			IDbConnection connection = null;
			IDbTransaction transaction = null;

			try
			{
				connection = GetConnection();
				if (connection == null) throw new ApplicationException("获取数据库连接失败");
				transaction = connection.BeginTransaction();
				return InsertMultipleImpl<T>(connection, transaction, t);
			}
			catch (Exception)
			{
				transaction?.Dispose();
				CloseConnection(connection);
				throw new Exception("插入多条数据出错");
			}
			finally
			{
				transaction?.Dispose();
				CloseConnection(connection);
			}
		}


		/// <summary>
		/// 执行事务
		/// </summary>
		/// <param name="sql">事务语句集</param>
		/// <param name="param">参数，可选，匿名类型</param>
		/// <param name="commandTimeOut">执行超时时间，可选，默认10秒</param>
		/// <param name="commandType">命令类型，可选，默认是CommandType.Text</param>
		/// <returns>执行结果</returns>
		public int ExcuteTransaction(string sql, object param = null, int? commandTimeOut = 10, CommandType commandType = CommandType.Text)
		{
			IDbConnection connection = null;
			IDbTransaction transaction = null;

			try
			{
				connection = GetConnection();
				if (connection == null) throw new ApplicationException("获取数据库连接失败");
				transaction = connection.BeginTransaction();
				return ExcuteTransactionImpl(connection, transaction, sql, param, commandTimeOut, commandType);
			}
			catch
			{
				transaction?.Dispose();
				CloseConnection(connection);
				throw new Exception("执行事务出错");
			}
			finally
			{
				transaction?.Dispose();
				CloseConnection(connection);
			}
		}

		/// <summary>
		/// 更新单条数据
		/// </summary>
		/// <typeparam name="T">对象类型</typeparam>
		/// <param name="t">对象</param>
		/// <param name="where">where条件 如："where id = ...."</param>
		/// <returns>执行结果</returns>
		public int UpdateSingle<T>(T t, string where)
		{
			IDbConnection connection = null;
			try
			{

				connection = GetConnection();
				if (connection == null) throw new ApplicationException("获取数据库连接失败");
				return UpdateSingleImpl(connection, t, where);
			}
			catch
			{
				CloseConnection(connection);
				throw new Exception("更新单条数据出错");
			}
			finally
			{
				CloseConnection(connection);
			}

		}

		/// <summary>
		/// 更新单条数据
		/// </summary>
		/// <typeparam name="T">对象类型</typeparam>
		/// <param name="t">对象</param>
		/// <returns>执行结果</returns>
		public int UpdateSingle<T>(T t)
		{
			IDbConnection connection = null;
			try
			{

				connection = GetConnection();
				if (connection == null) throw new ApplicationException("获取数据库连接失败");
				return UpdateSingleImpl(connection, t);
			}
			catch
			{
				CloseConnection(connection);
				throw new Exception("更新单条数据出错");
			}
			finally
			{
				CloseConnection(connection);
			}

		}

		/// <summary>
		/// 更新数据（sql）
		/// </summary>
		/// <param name="sql">sql</param>
		/// <param name="param">sql中需要的参数</param>
		/// <returns>更新结果</returns>
		public int UpdateBySQL(string sql, object param = null)
		{
			IDbConnection connection = null;
			IDbTransaction transaction = null;

			try
			{
				connection = GetConnection();
				if (connection == null) throw new ApplicationException("获取数据库连接失败");
				transaction = connection.BeginTransaction();
				return UpdateImpl(connection, transaction, sql, param);
			}
			catch
			{
				transaction?.Dispose();
				CloseConnection(connection);
				throw new Exception("更新数据（sql）出错");
			}
			finally
			{
				transaction?.Dispose();
				CloseConnection(connection);
			}
		}

		/// <summary>
		/// 更新数据的抽象方法
		/// </summary>
		/// <param name="connection">数据库连接</param>
		/// <param name="sql">SQL命令</param>
		/// <param name="param">参数</param>
		/// <returns>执行的结果</returns>
		public abstract int UpdateImpl(IDbConnection connection, IDbTransaction transaction, string sql, object param);

        /// <summary>
        /// 插入单条数据的抽象方法
        /// </summary>
        /// <typeparam name="T">插入的对象类型</typeparam>
        /// <param name="connection">数据库连接</param>
        /// <param name="t">要插入的对象</param>
        /// <returns>插入结果</returns>
        public abstract int InsertSingleDataImpl<T>(IDbConnection connection, T t);

		/// <summary>
		/// 插入多条数据的抽象方法
		/// </summary>
		/// <typeparam name="T">插入的对象类型</typeparam>
		/// <param name="connection">数据库连接</param>
		/// <param name="transaction">事务对象</param>
		/// <param name="t">要插入的对象</param>
		/// <returns>插入结果</returns>
		public abstract int InsertMultipleImpl<T>(IDbConnection connection, IDbTransaction transaction, IList<T> t);


		/// <summary>
		/// 执行事务抽象方法
		/// </summary>
		/// <param name="connection">数据库连接</param>
		/// <param name="transaction">事务对象</param>
		/// <param name="sql">SQL命令</param>
		/// <param name="param">参数，可选，匿名类型</param>
		/// <param name="commandTimeOut">执行超时时间，可选，默认10秒</param>
		/// <param name="commandType">命令类型，可选，默认是CommandType.Text</param>
		/// <returns>执行结果</returns>
		public abstract int ExcuteTransactionImpl(IDbConnection connection, IDbTransaction transaction, string sql, object param = null, int? commandTimeOut = 10, CommandType commandType = CommandType.Text);


		/// <summary>
		/// 更新单条数据抽象方法
		/// </summary>
		/// <typeparam name="T">更新的对象类型</typeparam>
		/// <param name="connection">数据库连接</param>
		/// <param name="t"></param>
		/// <param name="where">where 条件：如[xxx] = 'ffff' AND [sss] = 'bbbb'</param>
		/// <returns>执行结果</returns>
		public abstract int UpdateSingleImpl<T>(IDbConnection connection, T t, string where);


		/// <summary>
		/// 更新单条数据抽象方法
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="connection"></param>
		/// <param name="t"></param>
		/// <returns></returns>

		public abstract int UpdateSingleImpl<T>(IDbConnection connection, T t);
        
	}
}
